Return to start page

Systems/Character/Struct Abstract Quest.j

Code

		
1			library AStructSystemsCharacterAbstractQuest requires optional ALibraryCoreDebugMisc, ALibraryCoreEnvironmentSound, AStructCoreGeneralHashTable, ALibraryCoreStringConversion, AStructSystemsCharacterCharacter
2
3 /// @todo Should be a part of @struct AAbstractQuest, vJass bug.
4 function interface AAbstractQuestStateEvent takes AAbstractQuest abstractQuest, trigger usedTrigger returns nothing
5
6 /// @todo Should be a part of @struct AAbstractQuest, vJass bug.
7 function interface AAbstractQuestStateCondition takes AAbstractQuest abstractQuest returns boolean
8
9 /// @todo Should be a part of @struct AAbstractQuest, vJass bug.
10 function interface AAbstractQuestStateAction takes AAbstractQuest abstractQuest returns nothing
11
12 struct AAbstractQuest
13 //static constant members
14 public static constant integer stateNotUsed = -1
15 public static constant integer stateNew = 0
16 public static constant integer stateCompleted = 1
17 public static constant integer stateFailed = 2
18 public static constant integer rewardLevel = 0
19 public static constant integer rewardSkillPoints = 1
20 public static constant integer rewardExperience = 2
21 public static constant integer rewardStrength = 3
22 public static constant integer rewardAgility = 4
23 public static constant integer rewardIntelligence = 5
24 public static constant integer rewardGold = 6
25 public static constant integer rewardLumber = 7
26 private static constant integer maxStates = 3
27 private static constant integer maxRewards = 8
28 //static start members
29 private static real pingRate
30 private static string stateNewSoundPath
31 private static string stateCompletedSoundPath
32 private static string stateFailedSoundPath
33 private static string textStateNew
34 private static string textStateCompleted
35 private static string textStateFailed
36 private static string textRewardLevels
37 private static string textRewardSkillPoints
38 private static string textRewardExperience
39 private static string textRewardStrength
40 private static string textRewardAgility
41 private static string textRewardIntelligence
42 private static string textRewardGold
43 private static string textRewardLumber
44 //static members
45 private static AIntegerVector m_abstractQuests
46 private static timer m_pingTimer
47 //dynamic members
48 private integer m_state /// Should be setted by state method.
49 private AAbstractQuestStateCondition array m_stateCondition[thistype.maxStates]
50 private AAbstractQuestStateAction array m_stateAction[thistype.maxStates]
51 private integer array m_reward[thistype.maxRewards]
52 private boolean m_ping
53 private real m_pingX
54 private real m_pingY
55 private real m_pingDuration
56 private real m_pingRed
57 private real m_pingGreen
58 private real m_pingBlue
59 //start members
60 private ACharacter m_character
61 private string m_title
62 //members
63 private integer m_index
64 private trigger array m_stateTrigger[thistype.maxStates]
65
66 //! runtextmacro optional A_STRUCT_DEBUG("\"AAbstractQuest\"")
67
68 debug private method checkState takes integer state returns boolean
69 debug if ((state <= thistype.stateNotUsed) or (state >= thistype.maxStates)) then
70 debug call this.print("Wrong state: " + I2S(state) + ".")
71 debug return false
72 debug endif
73 debug return true
74 debug endmethod
75
76 //dynamic members
77
78 public stub method setState takes integer state returns nothing
79 debug if (this.checkState(state)) then
80 if (this.m_stateTrigger[state] == null) then
81 if (this.m_stateCondition[state] != 0 and not this.m_stateCondition[state].evaluate(this)) then
82 return
83 endif
84 endif
85 set this.m_state = state
86 if (state == thistype.stateNotUsed) then
87 if (this.m_stateTrigger[thistype.stateNew] != null) then
88 call EnableTrigger(this.m_stateTrigger[thistype.stateNew])
89 endif
90 if (this.m_stateTrigger[thistype.stateCompleted] != null) then
91 call DisableTrigger(this.m_stateTrigger[thistype.stateCompleted])
92 endif
93 if (this.m_stateTrigger[thistype.stateFailed] != null) then
94 call DisableTrigger(this.m_stateTrigger[thistype.stateFailed])
95 endif
96 elseif (state == thistype.stateNew) then
97 if (this.m_stateTrigger[thistype.stateNew] != null) then
98 call DisableTrigger(this.m_stateTrigger[thistype.stateNew])
99 endif
100 if (this.m_stateTrigger[thistype.stateCompleted] != null) then
101 call EnableTrigger(this.m_stateTrigger[thistype.stateCompleted])
102 endif
103 if (this.m_stateTrigger[thistype.stateFailed] != null) then
104 call EnableTrigger(this.m_stateTrigger[thistype.stateFailed])
105 endif
106 call this.displayMessage()
107 elseif (state == thistype.stateCompleted) then
108 if (this.m_stateTrigger[thistype.stateNew] != null) then
109 call DisableTrigger(this.m_stateTrigger[thistype.stateNew])
110 endif
111 if (this.m_stateTrigger[thistype.stateCompleted] != null) then
112 call DisableTrigger(this.m_stateTrigger[thistype.stateCompleted])
113 endif
114 if (this.m_stateTrigger[thistype.stateFailed] != null) then
115 call DisableTrigger(this.m_stateTrigger[thistype.stateFailed])
116 endif
117 call this.displayMessage()
118 call this.distributeRewards()
119 elseif (state == thistype.stateFailed) then
120 if (this.m_stateTrigger[thistype.stateNew] != null) then
121 call DisableTrigger(this.m_stateTrigger[thistype.stateNew])
122 endif
123 if (this.m_stateTrigger[thistype.stateCompleted] != null) then
124 call DisableTrigger(this.m_stateTrigger[thistype.stateCompleted])
125 endif
126 if (this.m_stateTrigger[thistype.stateFailed] != null) then
127 call DisableTrigger(this.m_stateTrigger[thistype.stateFailed])
128 endif
129 call this.displayMessage()
130 endif
131 if (this.m_stateAction[state] != 0) then
132 call this.m_stateAction[state].execute(this) //call custom function
133 endif
134 debug endif
135 endmethod
136
137 public method state takes nothing returns integer
138 return this.m_state
139 endmethod
140
141 //call first setStateEvent then setStateCondition and at least setStateAction
142 public method setStateEvent takes integer state, AAbstractQuestStateEvent stateEvent returns nothing
143 local conditionfunc conditionFunction
144 local triggercondition triggerCondition
145 local triggeraction triggerAction
146 debug if (not this.checkState(state)) then
147 debug return
148 debug endif
149 if (this.m_stateTrigger[state] == null) then
150 call this.createStateTrigger(state)
151 //else
152 endif
153 call stateEvent.execute(this, this.m_stateTrigger[state])
154 endmethod
155
156 public method setStateCondition takes integer state, AAbstractQuestStateCondition stateCondition returns nothing
157 debug if (not this.checkState(state)) then
158 debug return
159 debug endif
160 set this.m_stateCondition[state] = stateCondition
161 endmethod
162
163 public method stateCondition takes integer state returns AAbstractQuestStateCondition
164 debug if (not this.checkState(state)) then
165 debug return 0
166 debug endif
167 return this.m_stateCondition[state]
168 endmethod
169
170 public method setStateAction takes integer state, AAbstractQuestStateAction stateAction returns nothing
171 debug if (not this.checkState(state)) then
172 debug return
173 debug endif
174 set this.m_stateAction[state] = stateAction
175 endmethod
176
177 public method stateAction takes integer state returns AAbstractQuestStateAction
178 debug if (not this.checkState(state)) then
179 debug return 0
180 debug endif
181 return this.m_stateAction[state]
182 endmethod
183
184 public method setReward takes integer reward, integer value returns nothing
185 set this.m_reward[reward] = value
186 endmethod
187
188 public method reward takes integer reward returns integer
189 return this.m_reward
190 endmethod
191
192 public method setPing takes boolean ping returns nothing
193 set this.m_ping = ping
194 endmethod
195
196 public method ping takes nothing returns boolean
197 return this.m_ping
198 endmethod
199
200 public method setPingX takes real pingX returns nothing
201 set this.m_pingX = pingX
202 endmethod
203
204 public method pingX takes nothing returns real x
205 return this.m_pingX
206 endmethod
207
208 public method setPingY takes real pingY returns nothing
209 set this.m_pingY = pingY
210 endmethod
211
212 public method pingY takes nothing returns real
213 return this.m_pingY
214 endmethod
215
216 public method setPingDuration takes real pingDuration returns nothing
217 set this.m_pingDuration = pingDuration
218 endmethod
219
220 public method pingDuration takes nothing returns real
221 return this.m_pingDuration
222 endmethod
223
224 /// @param pingRed Default is 100.0.
225 public method setPingRed takes real pingRed returns nothing
226 set this.m_pingRed = pingRed
227 endmethod
228
229 public method pingRed takes nothing returns real
230 return this.m_pingRed
231 endmethod
232
233 /// @param pingGreen Default is 100.0.
234 public method setPingGreen takes real pingGreen returns nothing
235 set this.m_pingGreen = pingGreen
236 endmethod
237
238 public method pingGreen takes nothing returns real
239 return this.m_pingGreen
240 endmethod
241
242 /// @param pingBlue Default is 100.0.
243 public method setPingBlue takes real pingBlue returns nothing
244 set this.m_pingBlue = pingBlue
245 endmethod
246
247 public method pingBlue takes nothing returns real
248 return this.m_pingBlue
249 endmethod
250
251 //start members
252
253 public method character takes nothing returns ACharacter
254 return this.m_character
255 endmethod
256
257 public method title takes nothing returns string
258 return this.m_title
259 endmethod
260
261 //convenience methods
262
263 public method setPingLocation takes location usedLocation returns nothing
264 set this.m_pingX = GetLocationX(usedLocation)
265 set this.m_pingY = GetLocationY(usedLocation)
266 endmethod
267
268 public method setPingRect takes rect usedRect returns nothing
269 set this.m_pingX = GetRectCenterX(usedRect)
270 set this.m_pingY = GetRectCenterY(usedRect)
271 endmethod
272
273 public method setPingWidget takes widget usedWidget returns nothing
274 set this.m_pingX = GetWidgetX(usedWidget)
275 set this.m_pingY = GetWidgetY(usedWidget)
276 endmethod
277
278 public method setPingUnit takes unit usedUnit returns nothing
279 set this.m_pingX = GetUnitX(usedUnit)
280 set this.m_pingY = GetUnitY(usedUnit)
281 endmethod
282
283 public method setPingDestructable takes destructable usedDestructable returns nothing
284 set this.m_pingX = GetDestructableX(usedDestructable)
285 set this.m_pingY = GetDestructableY(usedDestructable)
286 endmethod
287
288 public method setPingItem takes item usedItem returns nothing
289 set this.m_pingX = GetItemX(usedItem)
290 set this.m_pingY = GetItemY(usedItem)
291 endmethod
292
293 public method setPingColour takes real red, real green, real blue returns nothing
294 set this.m_pingRed = red
295 set this.m_pingGreen = green
296 set this.m_pingBlue = blue
297 endmethod
298
299 //methods
300
301 public method getModifiedTitle takes nothing returns string
302 if (this.m_state == thistype.stateNew) then
303 return StringArg(thistype.textStateNew, this.m_title)
304 elseif (this.m_state == thistype.stateCompleted) then
305 return StringArg(thistype.textStateCompleted, this.m_title)
306 elseif (this.m_state == thistype.stateFailed) then
307 return StringArg(thistype.textStateFailed, this.m_title)
308 debug else
309 debug call this.print("Unknown state (in getModifiedTitle()): " + I2S(this.m_state))
310 endif
311 return this.m_title
312 endmethod
313
314 private method getSoundPath takes nothing returns string
315 if (this.m_state == thistype.stateNew) then
316 return thistype.stateNewSoundPath
317 elseif (this.m_state == thistype.stateCompleted) then
318 return thistype.stateCompletedSoundPath
319 else
320 return thistype.stateFailedSoundPath
321 endif
322 return ""
323 endmethod
324
325 private method displayMessage takes nothing returns nothing
326 if (this.m_character != 0) then
327 call this.m_character.displayMessage(ACharacter.messageTypeInfo, this.getModifiedTitle())
328 call PlaySoundPathForPlayer(this.m_character.user(), this.getSoundPath())
329 else
330 call ACharacter.displayMessageToAll(ACharacter.messageTypeInfo, this.getModifiedTitle())
331 call PlaySound(this.getSoundPath())
332 endif
333 endmethod
334
335 private method displayRewardMessage takes integer reward returns nothing
336 local string message
337 if (reward == thistype.rewardLevel) then
338 set message = thistype.textRewardLevels
339 elseif (reward == thistype.rewardSkillPoints) then
340 set message = thistype.textRewardSkillPoints
341 elseif (reward == thistype.rewardExperience) then
342 set message = thistype.textRewardExperience
343 elseif (reward == thistype.rewardStrength) then
344 set message = thistype.textRewardStrength
345 elseif (reward == thistype.rewardAgility) then
346 set message = thistype.textRewardAgility
347 elseif (reward == thistype.rewardIntelligence) then
348 set message = thistype.textRewardIntelligence
349 elseif (reward == thistype.rewardGold) then
350 set message = thistype.textRewardGold
351 elseif (reward == thistype.rewardLumber) then
352 set message = thistype.textRewardLumber
353 debug else
354 debug call this.print("Unknown reward: " + I2S(reward))
355 endif
356
357 set message = IntegerArg(message, this.m_reward[reward])
358
359 if (this.m_character != 0) then
360 call this.m_character.displayMessage(ACharacter.messageTypeInfo, message)
361 else
362 call ACharacter.displayMessageToAll(ACharacter.messageTypeInfo, message)
363 endif
364 endmethod
365
366 private method distributeRewards takes nothing returns nothing
367 local integer i
368 if (this.m_character != 0) then
369 if (this.m_reward[thistype.rewardLevel] != 0) then
370 call this.m_character.addLevels(this.m_reward[thistype.rewardLevel], true)
371 endif
372 if (this.m_reward[thistype.rewardSkillPoints] != 0) then
373 call this.m_character.addSkillPoints(this.m_reward[thistype.rewardSkillPoints])
374 endif
375 if (this.m_reward[thistype.rewardExperience] != 0) then
376 call this.m_character.addExperience(this.m_reward[thistype.rewardExperience], true)
377 endif
378 if (this.m_reward[thistype.rewardStrength] != 0) then
379 call this.m_character.addStrength(this.m_reward[thistype.rewardStrength])
380 endif
381 if (this.m_reward[thistype.rewardAgility] != 0) then
382 call this.m_character.addAgility(this.m_reward[thistype.rewardAgility])
383 endif
384 if (this.m_reward[thistype.rewardIntelligence] != 0) then
385 call this.m_character.addIntelligence(this.m_reward[thistype.rewardIntelligence])
386 endif
387 if (this.m_reward[thistype.rewardGold] != 0) then
388 call this.m_character.addGold(this.m_reward[thistype.rewardGold])
389 endif
390 if (this.m_reward[thistype.rewardLumber] != 0) then
391 call this.m_character.addLumber(this.m_reward[thistype.rewardLumber])
392 endif
393 else
394 if (this.m_reward[thistype.rewardLevel] != 0) then
395 call ACharacter.addLevelsToAll(this.m_reward[thistype.rewardLevel], true)
396 endif
397 if (this.m_reward[thistype.rewardSkillPoints] != 0) then
398 call ACharacter.addSkillPointsToAll(this.m_reward[thistype.rewardSkillPoints])
399 endif
400 if (this.m_reward[thistype.rewardExperience] != 0) then
401 call ACharacter.addExperienceToAll(this.m_reward[thistype.rewardExperience], true)
402 endif
403 if (this.m_reward[thistype.rewardStrength] != 0) then
404 call ACharacter.addStrengthToAll(this.m_reward[thistype.rewardStrength])
405 endif
406 if (this.m_reward[thistype.rewardAgility] != 0) then
407 call ACharacter.addAgilityToAll(this.m_reward[thistype.rewardAgility])
408 endif
409 if (this.m_reward[thistype.rewardIntelligence] != 0) then
410 call ACharacter.addIntelligenceToAll(this.m_reward[thistype.rewardIntelligence])
411 endif
412 if (this.m_reward[thistype.rewardGold] != 0) then
413 call ACharacter.addGoldToAll(this.m_reward[thistype.rewardGold])
414 endif
415 if (this.m_reward[thistype.rewardLumber] != 0) then
416 call ACharacter.addLumberToAll(this.m_reward[thistype.rewardLumber])
417 endif
418 endif
419 set i = 0
420 loop
421 exitwhen(i == thistype.maxRewards)
422 if (this.m_reward[i] != 0) then
423 call this.displayRewardMessage(i)
424 endif
425 set i = i + 1
426 endloop
427 endmethod
428
429 private static method triggerConditionRunQuestState takes nothing returns boolean
430 local trigger triggeringTrigger = GetTriggeringTrigger()
431 local thistype this = AHashTable.global().handleInteger(triggeringTrigger, "this")
432 local integer state = AHashTable.global().handleInteger(triggeringTrigger, "state")
433 local boolean result = true
434 if (this.m_stateCondition[state] != 0) then
435 set result = this.m_stateCondition[state].evaluate(this)
436 endif
437 set triggeringTrigger = null
438 return result
439 endmethod
440
441 private static method triggerActionRunQuestState takes nothing returns nothing
442 local trigger triggeringTrigger = GetTriggeringTrigger()
443 local thistype this = AHashTable.global().handleInteger(triggeringTrigger, "this")
444 local integer state = AHashTable.global().handleInteger(triggeringTrigger, "state")
445 /*
446 if (this.getType() == AQuest.typeid) then
447 call AQuest(this).setState(state)
448 debug call this.print("Is AQuest!")
449 elseif (this.getType() == AQuestItem.typeid) then
450 call AQuestItem(this).setState(state)
451 debug call this.print("Is AQuestItem!")
452 else
453 call this.setState(state) //custom function will be called in this method
454 debug call this.print("Is not AQuest and AQuestItem!")
455 endif
456 */
457 call this.setState(state)
458 set triggeringTrigger = null
459 endmethod
460
461 /// Condition and action definition must be above!!!!!!!!!!!!!!!!!!!!!!
462 private method createStateTrigger takes integer state returns nothing
463 local conditionfunc conditionFunction
464 local triggercondition triggerCondition
465 local triggeraction triggerAction
466 set this.m_stateTrigger[state] = CreateTrigger()
467 set conditionFunction = Condition(function thistype.triggerConditionRunQuestState)
468 set triggerCondition = TriggerAddCondition(this.m_stateTrigger[state], conditionFunction)
469 set triggerAction = TriggerAddAction(this.m_stateTrigger[state], function thistype.triggerActionRunQuestState)
470 call AHashTable.global().setHandleInteger(this.m_stateTrigger[state], "this", this)
471 call AHashTable.global().setHandleInteger(this.m_stateTrigger[state], "state", state)
472 if ((this.m_state != thistype.stateNew and state != thistype.stateNew) or (this.m_state == thistype.stateFailed or this.m_state == thistype.stateCompleted)) then /// new should be enable by default
473 call DisableTrigger(this.m_stateTrigger[state])
474 endif
475 set conditionFunction = null
476 set triggerCondition = null
477 set triggerAction = null
478 endmethod
479
480 public static method create takes ACharacter character, string title returns thistype
481 local thistype this = thistype.allocate()
482 //dynamic members
483 set this.m_state = thistype.stateNotUsed
484 //start members
485 set this.m_character = character
486 set this.m_title = title
487 //static members
488 call thistype.m_abstractQuests.pushBack(this)
489 //members
490 set this.m_index = thistype.m_abstractQuests.backIndex()
491
492 return this
493 endmethod
494
495 private method destroyStateTriggers takes nothing returns nothing
496 local integer i = 0
497 loop
498 exitwhen (i == thistype.maxStates)
499 if (this.m_stateTrigger[i] != null) then
500 call AHashTable.global().destroyTrigger(this.m_stateTrigger[i])
501 set this.m_stateTrigger[i] = null
502 endif
503 set i = i + 1
504 endloop
505 endmethod
506
507 public method onDestroy takes nothing returns nothing
508 //static members
509 call thistype.m_abstractQuests.erase(this.m_index)
510
511 call this.destroyStateTriggers()
512 endmethod
513
514 private static method timerFunctionPing takes nothing returns nothing
515 local thistype abstractQuest
516 local player user
517 local integer i = thistype.m_abstractQuests.backIndex()
518 loop
519 exitwhen (i < 0)
520 set abstractQuest = thistype.m_abstractQuests[i]
521 if (abstractQuest.m_ping and abstractQuest.m_state == thistype.stateNew) then
522 if (abstractQuest.m_character != 0) then
523 set user = abstractQuest.m_character.user()
524 call PingMinimapExForPlayer(user, abstractQuest.m_pingX, abstractQuest.m_pingY, abstractQuest.m_pingDuration, abstractQuest.m_pingRed, abstractQuest.m_pingGreen, abstractQuest.m_pingBlue, true)
525 set user = null
526 else
527 call PingMinimapEx(abstractQuest.m_pingX, abstractQuest.m_pingY, abstractQuest.m_pingDuration, PercentTo255(abstractQuest.m_pingRed), PercentTo255(abstractQuest.m_pingGreen), PercentTo255(abstractQuest.m_pingBlue), true)
528 endif
529 endif
530 set i = i - 1
531 endloop
532 endmethod
533
534 /// @param pingRate If this value is 0.0 or smaller there won't be any pings.
535 public static method init takes real pingRate, string stateNewSoundPath, string stateCompletedSoundPath, string stateFailedSoundPath, string textStateNew, string textStateCompleted, string textStateFailed, string textRewardLevels, string textRewardSkillPoints, string textRewardExperience, string textRewardStrength, string textRewardAgility, string textRewardIntelligence, string textRewardGold, string textRewardLumber returns nothing
536 //static start members
537 set thistype.pingRate = pingRate
538 set thistype.stateNewSoundPath = stateNewSoundPath
539 set thistype.stateCompletedSoundPath = stateCompletedSoundPath
540 set thistype.stateFailedSoundPath = stateFailedSoundPath
541 set thistype.textStateNew = textStateNew
542 set thistype.textStateCompleted = textStateCompleted
543 set thistype.textStateFailed = textStateFailed
544 set thistype.textRewardLevels = textRewardLevels
545 set thistype.textRewardSkillPoints = textRewardSkillPoints
546 set thistype.textRewardExperience = textRewardExperience
547 set thistype.textRewardStrength = textRewardStrength
548 set thistype.textRewardAgility = textRewardAgility
549 set thistype.textRewardIntelligence = textRewardIntelligence
550 set thistype.textRewardGold = textRewardGold
551 set thistype.textRewardLumber = textRewardLumber
552 //static members
553 set thistype.m_abstractQuests = AIntegerVector.create()
554 if (thistype.pingRate > 0.0) then
555 set thistype.m_pingTimer = CreateTimer()
556 call TimerStart(thistype.m_pingTimer, thistype.pingRate, true, function thistype.timerFunctionPing)
557 endif
558
559 if (stateNewSoundPath != null) then
560 call PreloadSoundPath(stateNewSoundPath)
561 endif
562 if (stateCompletedSoundPath != null) then
563 call PreloadSoundPath(stateCompletedSoundPath)
564 endif
565 if (stateFailedSoundPath != null) then
566 call PreloadSoundPath(stateFailedSoundPath)
567 endif
568 endmethod
569
570 public static method cleanUp takes nothing returns nothing
571 loop
572 exitwhen (thistype.m_abstractQuests.empty())
573 call thistype(thistype.m_abstractQuests.back()).destroy()
574 endloop
575 //static members
576 call thistype.m_abstractQuests.destroy()
577 if (thistype.pingRate > 0.0) then
578 call DestroyTimer(thistype.m_pingTimer)
579 set thistype.m_pingTimer = null
580 endif
581 endmethod
582
583 public static method enablePing takes nothing returns nothing
584 if (thistype.pingRate != 0.0) then
585 call ResumeTimer(thistype.m_pingTimer)
586 debug else
587 debug call thistype.staticPrint("There is no ping timer.")
588 endif
589 endmethod
590
591 public static method disablePing takes nothing returns nothing
592 if (thistype.pingRate != 0.0) then
593 call PauseTimer(thistype.m_pingTimer)
594 debug else
595 debug call thistype.staticPrint("There is no ping timer.")
596 endif
597 endmethod
598 endstruct
599
600 endlibrary